<template>
  <div class="app-container product">
    <el-form label-width="150px" size="small" @click.native="closePopover">
          <div style="padding-bottom:10px">
            <el-row>
              <el-col :span="18">
                <el-input v-model="norm.title" size="small" placeholder="如颜色，尺寸" style="width:300px">
              <template slot="prepend">规格名称</template>
            </el-input>
            <el-button type="primary" size="small" @click="normAdd">添加</el-button>
              </el-col>
              <el-col :span="6">
                <el-button type="danger" size="small" icon="el-icon-apple" @click="reset">重置</el-button>
                <el-button type="success" size="small" icon="el-icon-hot-water" @click="load">加载规格数据</el-button>
              </el-col>
            </el-row>
            
          </div>
          <el-table :data="normall" :default-sort="{prop:'sort',order: 'ascending'}" border>
            <el-table-column label="规格名" align="center">
              <template slot-scope="scope">
                <el-popover :ref="`popover-${scope.row.value}`" placement="top" trigger="manual" width="300px">
                  <div>
                    <el-input v-model="normedit.title" size="small" placeholder="" style="width:220px;"/>
                    <el-button type="success" size="small" @click.stop="normEditSave">保存</el-button>
                  </div>
                  <el-tag slot="reference" type="success" @click.stop="normEditShow(scope.$index,`popover-${scope.row.value}`)">{{ scope.row.title }}</el-tag>
                </el-popover>
              </template>
            </el-table-column>
            <el-table-column label="规格子项">
              <template slot-scope="scope">
                <el-row>
                  <el-col :span="4">
                    <el-popover :ref="`popover-${scope.row.value}-childadd`" placement="top" trigger="manual" width="300px" title="添加规格子项">
                      <div>
                        <el-input v-model="normchild.title" autofocus="true" size="small" placeholder="" style="width:220px;"/>
                        <el-button type="success" size="small" @click.stop="normChildAddSave">添加</el-button>
                      </div>
                      <el-button slot="reference" type="success" circle plain size="mini" icon="el-icon-plus" @click.stop="normChildAddShow(scope.$index,`popover-${scope.row.value}-childadd`)"/>
                    </el-popover>
                  </el-col>
                  <el-col :span="20">
                    <draggable :list="scope.row.content" v-bind="{group:scope.row.value}" @end="normChildDragEnd">
                      <el-popover v-for="(child,i) in scope.row.content" :ref="`popover-${scope.row.value}-${child.id}`" :key="child.id" placement="top" trigger="manual" width="300px">
                        <div>
                          <el-input v-model="normchild.title" size="small" placeholder="" style="width:220px;"/>
                          <el-button type="success" size="small" @click.stop="normChildEditSave">保存</el-button>
                        </div>
                        <div slot="reference" class="tag-panel">
                          <el-tag closable size="small" type="" @close="normChildClose(scope.$index,i)" @click.stop="normChildEditShow(scope.$index,i,`popover-${scope.row.value}-${child.id}`)">{{ child.title }}</el-tag>
                        </div>
                      </el-popover>
                    </draggable>
                  </el-col>
                </el-row>
              </template>
            </el-table-column>
            <el-table-column label="排序" prop="sort" class-name="sortpanel" align="center" width="150">
              <template slot-scope="scope">
                <sortedit :row.sync="scope.row" :list.sync="normall" rowkey="value" @sortEditSave="normSortEdit" />
              </template>
            </el-table-column>
            <el-table-column label="操作" width="120" align="center">
              <template slot-scope="scope">
                <el-button type="warning" circle plain size="mini" icon="el-icon-close" @click="normClose(scope.$index)"/>
              </template>
            </el-table-column>
          </el-table>
          <div v-if="normtable.length>0">
            <el-alert :closable="false" center type="success" title="商品各规格的库存/价格"/>
            <el-table :v-loading="normtableloading" :data="normtable" :span-method="objectSpanMethod" border>
              <el-table-column v-for="(norm,k) in norms" :key="k" :label="norm.title" :prop="norm.value" width="80" align="center"/>
              <el-table-column v-for="(col,k) in normpricecols" :key="col.value" :label="col.text" :prop="col.value" width="150" align="center" class-name="normcolumn">
                <template slot="header" slot-scope="scope">
                  <div class="normtableheader">
                    <div style="display:block">{{ col.text }}</div>
                    <div>
                      <el-input v-model="col.num" :ref="`normheader-${scope.$index}-${col.value}`" size="mini" clearable @keyup.native="normPriceMuiKeyUp(k,`normheader-${scope.$index}-${col.value}`)" />
                      <el-button circle class="" title="批量设置" icon="el-icon-d-arrow-right" size="mini" @click="normPriceMuiSet(k)"/>
                    </div>
                  </div>
                </template>
                <template slot-scope="scope">
                  <el-input :ref="`normprice-${scope.$index}-${col.value}`" v-model="scope.row[col.value]" size="small" clearable @keyup.native="normPriceKeyUp(scope.$index,k,`normprice-${scope.$index}-${col.value}`)" />
                </template>
              </el-table-column>
            </el-table>
          </div>

    </el-form>
    <div style="margin-top:20px">
      <el-alert type="success" title="规格结构数据" center effect="dark"></el-alert>
      <el-input :value="JSON.stringify(norms)" placeholder="" type="textarea" rows="6"></el-input>
    </div>
    <div style="margin-top:20px">
      <el-alert type="success" title="规格内容数据" center effect="dark"></el-alert>
      <el-input :value="JSON.stringify(normtable)" placeholder="" type="textarea" rows="6"></el-input>
    </div>

  </div>
      
</template>

<script>


import draggable from 'vuedraggable'
import sortedit from '@/components/SortEdit'
import { spaceClear, decimalFormat,getDateRand } from '@/utils/index'


var normstable = []
var oldnormstable = []

//规格内容表头
var normpricecols = [
  {
    text: '商品条码', value: 'productsn', num: '', decimal: -1
  },
  {
    text: '库存(件)', value: 'stock', num: '', decimal: 0
  },
  {
    text: '现价', value: 'marketprice', num: '', decimal: 2
  },
  {
    text: '原价', value: 'productprice', num: '', decimal: 2
  },
  {
    text: '成本价', value: 'costprice', num: '', decimal: 2
  },
  {
    text: '重量(kg)', value: 'weight', num: '', decimal: 2
  },
  {
    text: '体积', value: 'goods_size', num: '', decimal: 2
  }
]

var popoverid

export default {
  components:{draggable,sortedit},
  data(){
    return {
      norm: { title: '', value: '', sort: 0 },
      normedit: { title: '', normindex: 0 },
      normchild: { title: '', id: '', sort: 0, normindex: 0, childindex: 0 },
      normall: [], // 所有规格（包括无属性的规格）
      norms: [], // 实际用到的规格
      normtable: [], // 规格价格表，Array
      normtableloading: true,
      normpricecols:normpricecols
    }
  },
  methods:{
    reset(){
      this.normall = []
      this.norms = []
      this.normtable = []
    },
    load(){
      this.normall = [{"title":"颜色","value":"gg160378784589593","sort":0,"content":[{"id":"sx160378784992795","title":"红","sort":0},{"id":"sx160378785473554","title":"绿","sort":1},{"id":"sx160378785881566","title":"蓝","sort":2}]},{"title":"尺寸","value":"gg160378786289588","sort":1,"content":[{"id":"sx160378786560626","title":"大","sort":0},{"id":"sx160378787692725","title":"小","sort":1}]}]
      this.norms = [{"title":"颜色","value":"gg160378784589593","sort":0,"content":[{"id":"sx160378784992795","title":"红","sort":0},{"id":"sx160378785473554","title":"绿","sort":1},{"id":"sx160378785881566","title":"蓝","sort":2}]},{"title":"尺寸","value":"gg160378786289588","sort":1,"content":[{"id":"sx160378786560626","title":"大","sort":0},{"id":"sx160378787692725","title":"小","sort":1}]}]
      this.normtable =[{"option_id":0,"productsn":"202011","stock":"100","marketprice":"51","productprice":"80","costprice":"31","weight":"1.2","goods_size":"51","gg160378786289588":"大","gg160378786289588_id":"sx160378786560626","row_gg160378784589593":2,"gg160378784589593":"红","gg160378784589593_id":"sx160378784992795"},{"option_id":0,"productsn":"202022","stock":"200","marketprice":"50","productprice":"85","costprice":"32","weight":"1.3","goods_size":"52","gg160378786289588":"小","gg160378786289588_id":"sx160378787692725","gg160378784589593":"红","gg160378784589593_id":"sx160378784992795"},{"option_id":0,"productsn":"202033","stock":"300","marketprice":"52","productprice":"80","costprice":"33","weight":"1.4","goods_size":"53","gg160378786289588":"大","gg160378786289588_id":"sx160378786560626","row_gg160378784589593":2,"gg160378784589593":"绿","gg160378784589593_id":"sx160378785473554"},{"option_id":0,"productsn":"202044","stock":"400","marketprice":"50","productprice":"85","costprice":"34","weight":"1.5","goods_size":"54","gg160378786289588":"小","gg160378786289588_id":"sx160378787692725","gg160378784589593":"绿","gg160378784589593_id":"sx160378785473554"},{"option_id":0,"productsn":"202055","stock":"500","marketprice":"53","productprice":"80","costprice":"35","weight":"1.4","goods_size":"55","gg160378786289588":"大","gg160378786289588_id":"sx160378786560626","row_gg160378784589593":2,"gg160378784589593":"蓝","gg160378784589593_id":"sx160378785881566"},{"option_id":0,"productsn":"202066","stock":"600","marketprice":"50","productprice":"85","costprice":"36","weight":"1.3","goods_size":"56","gg160378786289588":"小","gg160378786289588_id":"sx160378787692725","gg160378784589593":"蓝","gg160378784589593_id":"sx160378785881566"}]
    },
    normAdd() {
      var t = spaceClear(this.norm.title)
      if (t === '') {
        this.$message.error('请输入规格名称')
        return
      }
      // 规格唯一标识
      var v = 'gg' + getDateRand()
      var repeatname = false
      this.normall.forEach(item => {
        if (item.title === t || item.value === v) {
          repeatname = true
          return
        }
      })
      if (repeatname) {
        this.$message.error('规格名称已存在！')
        return
      }
      var sort = this.normall.length
      if (sort > 0) {
        sort = this.normall[sort - 1].sort + 1
      }
      var newnorm = {
        title: t, value: v, sort: sort, content: []
      }
      this.normall.push(newnorm)
      this.norm = {
        title: '', value: ''
      }
    },
    normEditShow(normindex, refname) {
      var title = this.normall[normindex].title
      this.normedit = { title: title, normindex: normindex }
      this.showPopover(refname)
    },
    normEditSave() {
      var title = this.normedit.title
      if (spaceClear(title) === '') {
        this.$message.error('请输入规格名称')
        return
      }
      var normindex = this.normedit.normindex
      var repeatname = false
      this.normall.forEach((item, k) => {
        if (item.title === title && k !== normindex) {
          repeatname = true
          return
        }
      })
      if (repeatname) {
        this.$message.error('规格名已存在！')
        return
      }
      this.normall[normindex].title = title
      this.norm = {
        title: '', normindex: 0
      }
      this.updateNormTable()
      this.closePopover()
    },
    normChildAddShow(normindex, refname) {
      this.normchild = { normindex: normindex }
      this.showPopover(refname)
    },
    normChildAddSave() {
      var childname = this.normchild.title
      if (spaceClear(childname) === '') {
        this.$message.error('请输入规格子项')
        return
      }
      var repertname = false
      var normindex = this.normchild.normindex
      this.normall[normindex].content.forEach(item => {
        if (item.title === childname) {
          repertname = true
          return
        }
      })
      if (repertname) {
        this.$message.error('同一规格下不允许存在相同的子项！')
        return
      }
      // 规格子项唯一标识
      var id = 'sx' + getDateRand()
      var sort = this.normall[normindex].content.length
      var newchild = { id: id, title: childname, sort: sort}
      this.normall[normindex].content.push(Object.assign({}, newchild))
      this.updateNormTable()
      this.closePopover()
    },
    normChildEditShow(normindex, childindex, refname) {
      var norm = this.normall[normindex]
      var child = norm.content[childindex]
      this.normchild = Object.assign({ normindex: normindex, childindex: childindex }, child)
      this.showPopover(refname)
    },
    normChildEditSave() {
      var childname = this.normchild.title
      if (spaceClear(childname) === '') {
        this.$message.error('请输入规格值')
        return
      }
      var repertname = false
      var normindex = this.normchild.normindex
      var childindex = this.normchild.childindex
      this.normall[normindex].content.forEach((item, k) => {
        if (item.title === childname && k !== childindex) {
          repertname = true
          return
        }
      })
      if (repertname) {
        this.$message.error('同一规格下不允许存在相同的子项名！')
        return
      }

      this.normall[normindex].content[childindex].title = childname
      this.updateNormTable()
      this.closePopover()
    },
    normChildClose(normkey, childkey) {
      this.$confirm('移除此规格子项吗?', '删除提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.normall[normkey].content.splice(childkey, 1)
        this.updateNormTable()
      })
    },
    normClose(normkey) {
      this.$confirm('移除此规格吗，移除时此规格下的子项也将一同移除！', '删除提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.normall.splice(normkey, 1)
        this.updateNormTable()
      })
    },
    normPaneClick(e) {
      this.closePopover()
    },
    normSortEdit() {
      // 规格排序
      var norms = Object.assign([], this.normall)
      norms.sort(function(a, b) {
        return a.sort - b.sort
      })
      this.normall = norms
      this.updateNormTable()
    },
    normChildDragEnd() {
      console.log('normChildDragEnd')
      this.updateNormTable()
    },
    updateNormTable() {
      this.normtableloading = true
      // 规格数据如果无子类要去除计算
      var norms = []// 规格表结构
      var normprice = { option_id: 0 }// 后台规格id（添加时候默认0）
      this.normpricecols.forEach(item => {
        normprice[item.value] = ''// 为库存，原价等字段设置初始值，不设置可能有奇葩问题
      })
      this.normall.forEach(item => {
        if (item.content.length > 0) {
          norms.push(item)
        }
      })
      normstable = []// 创建新的规格价格表结构
      // 倒叙循环是为了让表格中规格从左到右合并显示
      var l = norms.length - 1
      while (l >= 0) {
        var norm = norms[l]

        // 规格循环后保存规格参数到公用table，其他不同规格循环时在原来保存table基础上加入新的规格信息
        if (normstable.length > 0) {
          if (norm.content.length > 0) {
            normstable = this.getNewTable(norm, normstable)
          }
        } else {
          norm.content.forEach(child => {
            var newrow = Object.assign({}, normprice)
            newrow[norm.value] = child.title
            newrow[norm.value + '_id'] = child.id
            normstable.push(newrow)
          })
        }
        l--
      }
      // console.log(norms)
      // console.log(normstable)
      this.norms = norms
      oldnormstable = Object.assign([], this.normtable)
      if (this.normtable.length > 0) {
        normstable.forEach((item, k) => {
          this.getTableRowPrices(k, normprice)
        })
      }
      this.normtable = normstable
      this.normtableloading = false
    },
    checkHasNormChild(row, item) {
      var hasnormchild = false
      var optionsame = true // 判断规格id是否全部匹配，如果增加或删除，则为false
      var norms = this.norms
      for (var i in norms) {
        const n = norms[i]
        const k = `${n.value}_id`
        // 如果增加新的规格，则原表格不会存在这个规格，所以要判断
        // 判断是否包含原来的规格，如果包含而且规格值相同，则保留原来数据
        if (item[k]) {
          if (row[k] === item[k]) {
            hasnormchild = true
          } else {
            hasnormchild = false
            optionsame = false
            return { hasnormchild: hasnormchild, optionsame: optionsame }
          }
        } else {
          optionsame = false
        }
      }
      return { hasnormchild: hasnormchild, optionsame: optionsame }
    },
    getTableRowPrices(index, normprice) {
      const row = normstable[index]
      for (var i in oldnormstable) {
        const item = oldnormstable[i]
        const ret = this.checkHasNormChild(row, item)
        if (ret.hasnormchild) {
          const oldrow = Object.assign({}, item)
          for (const j in normprice) {
            normstable[index][j] = oldrow[j]
          }
          if (!ret.optionsame) {
            normstable[index]['option_id'] = 0
          }
          return
        }
      }
    },
    getNewTable(norm, oldtable) {
      var newtable = []
      // 同一规格下子类与原表格循环合并
      norm.content.forEach(child => {
        var normtable = this.getNormTable(Object.assign([], oldtable), norm, child)
        newtable = newtable.concat(normtable)
      })
      return newtable
    },
    getNormTable(nowtable, norm, child) {
      var newtable = []
      // 原表格每行循环加入新的规格参数，然后返回新的表格
      nowtable.forEach((item, key) => {
        // var newrow = {}
        var newrow = Object.assign({}, item)
        if (key === 0) {
          newrow['row_' + norm.value] = nowtable.length
        }
        newrow[norm.value] = child.title
        newrow[norm.value + '_id'] = child.id
        // for (var k in item) {
        //   newrow[norm.value] = child.text
        //   newrow[k] = item[k]
        // }
        newtable.push(newrow)
      })
      return newtable
    },
    normPriceMuiKeyUp(i, refname) { // 规格价格表头部数值输入
      var decimal = this.normpricecols[i].decimal
      if (decimal >= 0) {
        var num = decimalFormat(this, refname, decimal)
        this.normpricecols[i].num = num
      }
    },
    normPriceKeyUp(i, k, refname) { // 规格价格表数值输入
      var decimal = this.normpricecols[k].decimal
      if (decimal >= 0) {
        var num = decimalFormat(this, refname, decimal)
        var v = this.normpricecols[k].value
        this.normtable[i][v] = num
      }
    },
    normPriceMuiSet(colkey) { // 规格价格表头部数值批量设置
      const n = spaceClear(this.normpricecols[colkey].num)
      if (n === '') {
        this.$message.error('请输入数值！')
        return
      }
      var v = this.normpricecols[colkey].value
      var normtable = Object.assign([], this.normtable)
      normtable.forEach((item, k) => {
        // Object.defineProperty(item, v, { get() { return n }, set(value) { v = value } })
        item[v] = n
      })
      this.normtable = normtable
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      // const row  // 当前行
      // const column // 当前列
      // const rowindex // 当前行号
      // const columnindex // 当前列号
      // 规格列中默认最后一列不合并行
      if (columnIndex < this.norms.length - 1) {
        var normvalue = this.norms[columnIndex].value
        // 如果有对应的行合并字段，则合并行
        if (row['row_' + normvalue]) {
          return {
            rowspan: row['row_' + normvalue], // 合并行数
            colspan: 1// 合并列数
          }
        } else {
          // 合并过的列
          return {
            rowspan: 0,
            colspan: 0
          }
        }
      } else {
        // 正常显示的列
        return {
          rowspan: 1,
          colspan: 1
        }
      }
    },
    showPopover(id) {
      // 通用弹框显示
      // 1.判断原弹框是否存在，存在先关闭后再显示新的弹框
      if (popoverid) {
        const pop = this.$refs[popoverid][0]
        if (pop) {
          pop.doClose()
        }
      }
      var pop = this.$refs[id]
      if (pop.length > 0) {
        pop = pop[0]
      }
      if (pop) {
        pop.doShow()
        popoverid = id
      }
    },
    closePopover() {
      if (popoverid) {
        var pop = this.$refs[popoverid]
        if (pop.length > 0) {
          pop = pop[0]
        }
        if (pop) {
          pop.doClose()
        }
        popoverid = null
      }
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" >
.product{
  .el-popover__title {
    color: #67C23A;
  }
  .tag-panel{
    display:inline-block;margin-right: 5px
  }
 .el-table th.normcolumn{
    padding: 5px 0;
  }
  .el-table .cell, .el-table th div{
    overflow:initial
  }
  .el-table th div.normtableheader,.el-table th div.normtableheader div{
    padding: 0;line-height: 20px;margin: 0;
  }
  .normtableheader .el-input{
    width: 80px;vertical-align: middle;
  }
  .normtableheader .el-button{
    vertical-align: middle;transform: rotate(90deg)
  }

}



</style>